<template>
  <div class="dynamic-form">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="120px"
      size="default"
    >
      <template v-for="(field, key) in formFields" :key="key">
        <el-form-item
          :label="field.title || key"
          :prop="key"
          :required="field.required"
        >
          <!-- 字符串类型 -->
          <template v-if="field.type === 'string'">
            <!-- 枚举选择 -->
            <el-select
              v-if="field.enum"
              v-model="formData[key]"
              :placeholder="field.description || `请选择${field.title || key}`"
              clearable
              style="width: 100%"
            >
              <el-option
                v-for="option in field.enum"
                :key="option"
                :label="option"
                :value="option"
              />
            </el-select>
            <!-- 多行文本 -->
            <el-input
              v-else-if="field.format === 'textarea'"
              v-model="formData[key]"
              type="textarea"
              :rows="field.rows || 3"
              :placeholder="field.description || `请输入${field.title || key}`"
              :maxlength="field.maxLength"
              show-word-limit
            />
            <!-- 密码输入 -->
            <el-input
              v-else-if="field.format === 'password'"
              v-model="formData[key]"
              type="password"
              :placeholder="field.description || `请输入${field.title || key}`"
              :maxlength="field.maxLength"
              show-password
            />
            <!-- 普通文本 -->
            <el-input
              v-else
              v-model="formData[key]"
              :placeholder="field.description || `请输入${field.title || key}`"
              :maxlength="field.maxLength"
              clearable
            />
          </template>

          <!-- 数字类型 -->
          <template v-else-if="field.type === 'number' || field.type === 'integer'">
            <el-input-number
              v-model="formData[key]"
              :min="field.minimum"
              :max="field.maximum"
              :step="field.type === 'integer' ? 1 : 0.1"
              :precision="field.type === 'integer' ? 0 : 2"
              :placeholder="field.description || `请输入${field.title || key}`"
              style="width: 100%"
            />
          </template>

          <!-- 布尔类型 -->
          <template v-else-if="field.type === 'boolean'">
            <el-switch
              v-model="formData[key]"
              :active-text="field.trueLabel || '是'"
              :inactive-text="field.falseLabel || '否'"
            />
          </template>

          <!-- 数组类型 -->
          <template v-else-if="field.type === 'array'">
            <div class="array-field">
              <div
                v-for="(item, index) in formData[key]"
                :key="index"
                class="array-item"
              >
                <div class="array-item-content">
                  <!-- 简单数组项 -->
                  <template v-if="isSimpleArrayItem(field.items)">
                    <el-input
                      v-if="field.items.type === 'string'"
                      v-model="formData[key][index]"
                      :placeholder="`请输入${field.title || key}项`"
                    />
                    <el-input-number
                      v-else-if="field.items.type === 'number' || field.items.type === 'integer'"
                      v-model="formData[key][index]"
                      :min="field.items.minimum"
                      :max="field.items.maximum"
                      :step="field.items.type === 'integer' ? 1 : 0.1"
                      style="width: 100%"
                    />
                  </template>
                  <!-- 复杂数组项 -->
                  <template v-else>
                    <DynamicForm
                      :schema="{ type: 'object', properties: field.items.properties }"
                      :model-value="formData[key][index]"
                      @update:model-value="updateArrayItem(key, index, $event)"
                    />
                  </template>
                </div>
                <div class="array-item-actions">
                  <el-button
                    type="danger"
                    size="small"
                    @click="removeArrayItem(key, index)"
                    :icon="Delete"
                    circle
                  />
                </div>
              </div>
              <el-button
                type="primary"
                size="small"
                @click="addArrayItem(key, field)"
                :icon="Plus"
                plain
              >
                添加项
              </el-button>
            </div>
          </template>

          <!-- 对象类型 -->
          <template v-else-if="field.type === 'object'">
            <div class="object-field">
              <DynamicForm
                v-if="field.properties"
                :schema="field"
                :model-value="formData[key]"
                @update:model-value="updateObjectField(key, $event)"
              />
              <el-input
                v-else
                v-model="objectJsonString[key]"
                type="textarea"
                :rows="3"
                placeholder="请输入JSON格式的对象"
                @blur="parseObjectJson(key)"
              />
            </div>
          </template>

          <!-- 其他类型或未知类型 -->
          <template v-else>
            <el-input
              v-model="formData[key]"
              :placeholder="field.description || `请输入${field.title || key}`"
            />
          </template>

          <!-- 字段描述 -->
          <div v-if="field.description" class="field-description">
            {{ field.description }}
          </div>
        </el-form-item>
      </template>
    </el-form>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Delete } from '@element-plus/icons-vue'

// Props
const props = defineProps({
  schema: {
    type: Object,
    required: true
  },
  modelValue: {
    type: Object,
    default: () => ({})
  }
})

// Emits
const emit = defineEmits(['update:modelValue'])

// 响应式数据
const formRef = ref()
const formData = ref({})
const objectJsonString = reactive({})

// 计算属性
const formFields = computed(() => {
  if (!props.schema || !props.schema.properties) {
    return {}
  }
  return props.schema.properties
})

const formRules = computed(() => {
  const rules = {}
  const required = props.schema.required || []
  
  Object.entries(formFields.value).forEach(([key, field]) => {
    const fieldRules = []
    
    // 必填验证
    if (required.includes(key)) {
      fieldRules.push({
        required: true,
        message: `${field.title || key}不能为空`,
        trigger: ['blur', 'change']
      })
    }
    
    // 字符串长度验证
    if (field.type === 'string') {
      if (field.minLength !== undefined) {
        fieldRules.push({
          min: field.minLength,
          message: `${field.title || key}长度不能少于${field.minLength}个字符`,
          trigger: 'blur'
        })
      }
      if (field.maxLength !== undefined) {
        fieldRules.push({
          max: field.maxLength,
          message: `${field.title || key}长度不能超过${field.maxLength}个字符`,
          trigger: 'blur'
        })
      }
      if (field.pattern) {
        fieldRules.push({
          pattern: new RegExp(field.pattern),
          message: field.patternMessage || `${field.title || key}格式不正确`,
          trigger: 'blur'
        })
      }
    }
    
    // 数字范围验证
    if (field.type === 'number' || field.type === 'integer') {
      if (field.minimum !== undefined) {
        fieldRules.push({
          type: 'number',
          min: field.minimum,
          message: `${field.title || key}不能小于${field.minimum}`,
          trigger: 'blur'
        })
      }
      if (field.maximum !== undefined) {
        fieldRules.push({
          type: 'number',
          max: field.maximum,
          message: `${field.title || key}不能大于${field.maximum}`,
          trigger: 'blur'
        })
      }
    }
    
    if (fieldRules.length > 0) {
      rules[key] = fieldRules
    }
  })
  
  return rules
})

// 方法定义
const initFormData = () => {
  const data = { ...props.modelValue }
  
  // 为每个字段设置默认值
  Object.entries(formFields.value).forEach(([key, field]) => {
    if (data[key] === undefined) {
      data[key] = getDefaultValue(field)
    }
    
    // 为对象类型字段初始化JSON字符串
    if (field.type === 'object' && !field.properties) {
      objectJsonString[key] = JSON.stringify(data[key] || {}, null, 2)
    }
  })
  
  formData.value = data
}

const getDefaultValue = (field) => {
  if (field.default !== undefined) {
    return field.default
  }
  
  switch (field.type) {
    case 'string':
      return ''
    case 'number':
    case 'integer':
      return field.minimum || 0
    case 'boolean':
      return false
    case 'array':
      return []
    case 'object':
      return {}
    default:
      return null
  }
}

const isSimpleArrayItem = (items) => {
  if (!items) return true
  return ['string', 'number', 'integer', 'boolean'].includes(items.type)
}

const addArrayItem = (key, field) => {
  if (!formData.value[key]) {
    formData.value[key] = []
  }
  
  const newItem = getDefaultValue(field.items || { type: 'string' })
  formData.value[key].push(newItem)
  emitUpdate()
}

const removeArrayItem = (key, index) => {
  formData.value[key].splice(index, 1)
  emitUpdate()
}

const updateArrayItem = (key, index, value) => {
  formData.value[key][index] = value
  emitUpdate()
}

const updateObjectField = (key, value) => {
  formData.value[key] = value
  emitUpdate()
}

const parseObjectJson = (key) => {
  try {
    const parsed = JSON.parse(objectJsonString[key])
    formData.value[key] = parsed
    emitUpdate()
  } catch (error) {
    ElMessage.error('JSON格式错误：' + error.message)
    // 恢复原值
    objectJsonString[key] = JSON.stringify(formData.value[key] || {}, null, 2)
  }
}

const emitUpdate = () => {
  emit('update:modelValue', { ...formData.value })
}

const validate = async () => {
  if (!formRef.value) return false
  
  try {
    await formRef.value.validate()
    return true
  } catch {
    return false
  }
}

const resetFields = () => {
  if (formRef.value) {
    formRef.value.resetFields()
  }
  initFormData()
}

const clearValidate = () => {
  if (formRef.value) {
    formRef.value.clearValidate()
  }
}

// 监听器
watch(
  () => props.modelValue,
  (newValue) => {
    if (JSON.stringify(newValue) !== JSON.stringify(formData.value)) {
      initFormData()
    }
  },
  { deep: true }
)

watch(
  () => props.schema,
  () => {
    nextTick(() => {
      initFormData()
    })
  },
  { deep: true }
)

watch(
  formData,
  () => {
    emitUpdate()
  },
  { deep: true }
)

// 暴露方法
defineExpose({
  validate,
  resetFields,
  clearValidate
})

// 初始化
initFormData()
</script>

<style scoped>
.dynamic-form {
  width: 100%;
}

.field-description {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
  line-height: 1.4;
}

.array-field {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 12px;
  background-color: #fafafa;
}

.array-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 12px;
  padding: 8px;
  background-color: #fff;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
}

.array-item:last-of-type {
  margin-bottom: 8px;
}

.array-item-content {
  flex: 1;
}

.array-item-actions {
  display: flex;
  align-items: center;
  margin-top: 4px;
}

.object-field {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 12px;
  background-color: #fafafa;
}

.object-field .dynamic-form {
  background-color: #fff;
  padding: 8px;
  border-radius: 4px;
}

/* 嵌套表单样式调整 */
.object-field :deep(.el-form-item) {
  margin-bottom: 16px;
}

.object-field :deep(.el-form-item__label) {
  font-size: 13px;
  color: #606266;
}

.array-item-content :deep(.el-form-item) {
  margin-bottom: 8px;
}

.array-item-content :deep(.el-form-item__label) {
  font-size: 12px;
  color: #909399;
  width: 80px !important;
}

/* 响应式布局 */
@media (max-width: 768px) {
  .dynamic-form :deep(.el-form-item__label) {
    width: 100px !important;
  }
  
  .array-item {
    flex-direction: column;
  }
  
  .array-item-actions {
    align-self: flex-end;
    margin-top: 8px;
  }
}
</style>